package com.derive.education_service.utils;

import com.derive.education_service.common.global.ResponseMessage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 封装一个用于上传文件资源的类
 * 单文件上传
 * 多文件上传
 * 下载文件
 * 删除文件
 *
 * @author xieyingde
 */
@Slf4j
@Component
public class MyFileUtils {

    @Value("${filePath}")
    private String filePath;


    /**
     * 将文件保存到指定的路径下
     * 单文件上传
     *
     * @param file
     * @return
     * @throws IOException
     */
    public ResponseMessage uploadFile(MultipartFile file, String path) throws IOException {
        System.out.println(filePath);
        // 检测文件是否存在
        if (file.isEmpty()) {
            return ResponseMessage.createByErrorMessage("文件不存在或为空");
        }
        //文件名 用作文件名称字段
        String fileName;
        // 新文件名 用作实际文件名称
        String newFileName;
        //文件拓展名
        String fileHzm;

        //获取文件拓展名
        fileHzm = FilenameUtils.getExtension(file.getOriginalFilename());
        //获取文件名 file.xx
        fileName = FilenameUtils.getName(file.getOriginalFilename());
        if (fileName.lastIndexOf(".") <= 0) {
            return ResponseMessage.createByErrorMessage("不支持该文件类型");
        }
        //新文件名 以pId命名
        newFileName = UUID.randomUUID().toString().replaceAll("-", "");
        // 创建文件对象
        File fileUrl = new File(filePath + File.separator + path);

        File uploadFile = new File(filePath + File.separator + path + File.separator + newFileName + "." + fileHzm);
        // 检测是否存在目录
        if (!uploadFile.getParentFile().exists()) {
            //创建文件路径
            fileUrl.mkdirs();
        }
        log.info("文件上传路径{[]}：" + fileUrl);
        //以绝对路径保存重命名后的文件
        // linux中不识别\ ，使用File.separator
        file.transferTo(uploadFile);
        //设置数据库保存路径
        String url = path + "/" + newFileName + "." + fileHzm;
        return ResponseMessage.createBySuccess("文件上传数据库使用路径", url.replace("\\","/"));
    }

    /**
     * 多文件上传
     *
     * @param request
     * @return
     */
    public ResponseMessage handleFileUpload(MyFileUtils myFileUtils, HttpServletRequest request, String filePath) {
        // 获取请求得到的多个文件
        List<MultipartFile> files = ((MultipartHttpServletRequest) request)
                .getFiles("file");
        BufferedOutputStream stream = null;
        List<String> list = new ArrayList<>();
        for (int i = 0; i < files.size(); i++) {
            try {
                // 这里上传文件
                ResponseMessage responseMessage = myFileUtils.uploadFile(files.get(i), filePath);
                list.add(String.valueOf(responseMessage.getData()));
            } catch (Exception e) {
                stream = null;
                e.printStackTrace();
                return ResponseMessage.createByErrorMessage("上传异常，异常信息为第" + i + "个文件产生 ==>" + e.getMessage());
            }
        }
        return ResponseMessage.createBySuccess("多文件上传成功", list);
    }

    /**
     * 下载文件
     *
     * @param path 上传文件路径+数据库存储的路径
     * @return
     */
    public ResponseMessage downloadFile(HttpServletResponse response, String path, String fileName) {
        File file = new File(filePath + File.separator + path);
        // 判断文件父目录是否存在
        if (file.exists()) {
            byte[] buffer = new byte[1024];
            FileInputStream fis = null; //文件输入流
            BufferedInputStream bis = null;
            OutputStream os = null; //输出流
            try {
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
                response.setCharacterEncoding("UTF-8");
                response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
                os = response.getOutputStream();
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer);
                    i = bis.read(buffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("文件下载失败，请重试====" + e.getMessage());
                return ResponseMessage.createByErrorMessage("文件下载失败，请重试");
            }
            try {
                bis.close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("===文件下载-流关闭异常====");
                e.printStackTrace();
            }
            log.info("----------成功下载文件==>---" + fileName);
            return ResponseMessage.createBySuccess("文件下载成功", fileName);
        } else {
            log.info("====文件不存在====");
            return ResponseMessage.createByErrorMessage("文件不存在，无法下载");
        }
    }

    /**
     * 删除文件
     *
     * @param path 上传文件路径+数据库存储的路径
     * @return
     */
    public ResponseMessage delFile(String path) {
        File file = new File(filePath + File.separator + path);
        // 判断文件或者目录是否存在
        if (!file.exists()) {
            return ResponseMessage.createByErrorMessage("删除失败，文件不存在");
        }
        // 判断是否是一个文件
        if (file.isFile() || file.list() == null) {
            boolean f = file.delete();
            if (f) {
                // 删除成功
                log.info("删除了===" + file.getName());
                // 删除数据库记录 返回根据状态来删除数据库记录
                return ResponseMessage.createBySuccessMessage("删除文件" + file.getName() + "成功");
            } else {
                return ResponseMessage.createByErrorMessage("删除文件" + file.getName() + "失败");
            }
        } else {
            return ResponseMessage.createByErrorMessage("该目录下不是一个文件对象");
        }
    }
}
